/**
  ******************************************************************************
  * 文件名称: BLDCMotor.cpp
  * 作    者: DoubaoAssistant
  * 版    本: V1.0
  * 日    期: 2025-04-26
  * 说    明: 基于STM32F103的无刷电机驱动类实现
  ******************************************************************************
  */

#include <cstdio>
#include "motor.h"
extern TIM_HandleTypeDef htim1;
// 在BLDCMotor.cpp文件中
BLDCMotor* BLDCMotor::instance = nullptr; // 正确的静态实例声明

BLDCMotor & BLDCMotor::getInstance() {
    if (!instance) {
        instance =new BLDCMotor(&htim1, TIM_CHANNEL_1, TIM_CHANNEL_2, TIM_CHANNEL_3);
    }
    return *instance;
}

// 构造函数实现
BLDCMotor::BLDCMotor(TIM_HandleTypeDef* timHandle,
                     uint32_t ch1, uint32_t ch2, uint32_t ch3)
    : htim(timHandle),
      pwmChannel1(ch1),
      pwmChannel2(ch2),
      pwmChannel3(ch3),
      currentStep(CommutationStep::STEP_1),
      motorSpeed(3600),  // 默认50%占空比（7200的一半）
      isRunning(false)
{
    motorSpeed=800;
    motorDirection = FORWARD;
}

// 初始化电机驱动
bool BLDCMotor::init()
{
    // 配置GPIO
    configureGPIO();

    // 配置定时器
    if (!configureTimer()) {
        return false;
    }

    // 使能TIM主输出（F1系列需要手动设置）
    htim->Instance->BDTR |= TIM_BDTR_MOE;

    return true;
}

void BLDCMotor::updateStep(uint32_t step) {
    positionStep=step;
}

// 启动电机
void BLDCMotor::start()
{
    // 启动PWM输出
    HAL_TIM_PWM_Start(htim, pwmChannel1);
    HAL_TIM_PWM_Start(htim, pwmChannel2);
    HAL_TIM_PWM_Start(htim, pwmChannel3);

    isRunning = true;
}

// 停止电机
void BLDCMotor::stop()
{
    // 停止PWM输出
    HAL_TIM_PWM_Stop(htim, pwmChannel1);
    HAL_TIM_PWM_Stop(htim, pwmChannel2);
    HAL_TIM_PWM_Stop(htim, pwmChannel3);

    isRunning = false;
}

// 设置电机转速
void BLDCMotor::setSpeed(uint16_t speed)
{
    // 限制最大转速
    if (speed > 2000) speed = 2000;

    motorSpeed = speed;

    // 如果电机正在运行，立即更新PWM占空比
    if (isRunning) {
        executeCommutation(CommutationStep::STEP_1);
    }
}

// 更新电机状态（根据位置信号换相）
void BLDCMotor::update()
{
    if (!isRunning) return;

    // 将全局位置信号转换为换向步骤
    if (positionStep >= 0 && positionStep <= 5) {
        currentStep = static_cast<CommutationStep>(positionStep);
    }
    // else {
    //     // 位置信号异常，默认使用STEP_1
    //     currentStep = CommutationStep::STEP_1;
    // }

    // 执行换相
    //executeCommutation();
}

bool BLDCMotor::startPWM()
{
    // 启动主输出和互补输出
    if (HAL_TIM_PWM_Start(htim, pwmChannel1) != HAL_OK ||
        HAL_TIM_PWM_Start(htim, pwmChannel2) != HAL_OK ||
        HAL_TIM_PWM_Start(htim, pwmChannel3) != HAL_OK ||
        HAL_TIMEx_PWMN_Start(htim, pwmChannel1) != HAL_OK ||
        HAL_TIMEx_PWMN_Start(htim, pwmChannel2) != HAL_OK ||
        HAL_TIMEx_PWMN_Start(htim, pwmChannel3) != HAL_OK) {
        return false;
        }

    return true;
}

// 配置定时器
bool BLDCMotor::configureTimer()
{
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

    // 配置PWM模式
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCPOLARITY_HIGH;  // 修改为LOW
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

    if (HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, pwmChannel1) != HAL_OK ||
        HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, pwmChannel2) != HAL_OK ||
        HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, pwmChannel3) != HAL_OK) {
        return false;
        }

    // 配置死区时间和刹车功能
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 100;           // ~2μs死区时间 @84MHz
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;

    if (HAL_TIMEx_ConfigBreakDeadTime(htim, &sBreakDeadTimeConfig) != HAL_OK) {
        return false;
    }

    // 启动PWM输出
    if (!startPWM()) {
        return false;
    }

    return true;
}

// 配置GPIO（兼容STM32F103）
void BLDCMotor::configureGPIO()
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 启用GPIO时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // 配置PWM输出引脚（PA8/PA9/PA10对应TIM1_CH1/CH2/CH3）
    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;

    // STM32F103最高GPIO速度为50MHz
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    // 配置复用功能（STM32F103使用不同的AF定义方式）
    // 对于STM32F103，PA8/PA9/PA10默认复用为TIM1
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 执行换相
void BLDCMotor::executeCommutation(CommutationStep step)
{
    if (isRunning==false) {
        return;
    }
    // 清除所有通道输出
    __HAL_TIM_SET_COMPARE(htim, pwmChannel1, 0);
    __HAL_TIM_SET_COMPARE(htim, pwmChannel2, 0);
    __HAL_TIM_SET_COMPARE(htim, pwmChannel3, 0);

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);

    // 若反转，则将 step 映射成 (7 - step)
    if (motorDirection == REVERSE) {
        step = static_cast<CommutationStep>(7 - static_cast<int>(step));
    }

    switch (step) {
        case CommutationStep::STEP_1: // U+ W-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel1, motorSpeed); // PA8 PWM
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET); // PA10 = 0
        break;
        case CommutationStep::STEP_2: // U+ V-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel1, motorSpeed);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); // PA9 = 0
        break;
        case CommutationStep::STEP_3: // V+ U-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel2, motorSpeed);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // PA8 = 0
        break;
        case CommutationStep::STEP_4: // V+ W-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel2, motorSpeed);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
        break;
        case CommutationStep::STEP_5: // W+ V-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel3, motorSpeed);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
        break;
        case CommutationStep::STEP_6: // W+ U-
            __HAL_TIM_SET_COMPARE(htim, pwmChannel3, motorSpeed);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
        break;
    }
}

void BLDCMotor::openLoopStart() {
    setDirection(MotorDirection::FORWARD);
    for (uint8_t i = 1; i < 60; ++i) {
        uint8_t step = (i % 6) ;
        executeCommutation(static_cast<CommutationStep>(step));
        HAL_Delay(5);
    }
}

void BLDCMotor::setDirection(MotorDirection dir) {
    this->motorDirection=dir;
}
